#ifndef U2Common_H
#define U2Common_H

#include "U2PreRequest.h"


U2EG_NAMESPACE_BEGIN



/// Name / value parameter pair (first = name, second = value)
typedef std::map<U2String, U2String>                NameValuePairList;



/** Structure used to define a box in a 3-D integer space.
 	Note that the left, top, and front edges are included but the right, 
 	bottom and back ones are not.
 */
struct Box
{
    size_t left, top, right, bottom, front, back;
	/// Parameterless constructor for setting the members manually
    Box()
		: left(0), top(0), right(1), bottom(1), front(0), back(1)
    {
    }
    /** Define a box from left, top, right and bottom coordinates
    	This box will have depth one (front=0 and back=1).
    	@param	l	x value of left edge
    	@param	t	y value of top edge
    	@param	r	x value of right edge
    	@param	b	y value of bottom edge
    	@note Note that the left, top, and front edges are included 
           	but the right, bottom and back ones are not.
    */
    Box( size_t l, size_t t, size_t r, size_t b ):
        left(l),
        top(t),   
        right(r),
        bottom(b),
        front(0),
        back(1)
    {
  		assert(right >= left && bottom >= top && back >= front);
    }
    /** Define a box from left, top, front, right, bottom and back
    	coordinates.
    	@param	l	x value of left edge
    	@param	t	y value of top edge
    	@param  ff  z value of front edge
    	@param	r	x value of right edge
    	@param	b	y value of bottom edge
    	@param  bb  z value of back edge
    	@note Note that the left, top, and front edges are included 
           	but the right, bottom and back ones are not.
    */
    Box( size_t l, size_t t, size_t ff, size_t r, size_t b, size_t bb ):
        left(l),
        top(t),   
        right(r),
        bottom(b),
        front(ff),
        back(bb)
    {
  		assert(right >= left && bottom >= top && back >= front);
    }
    
    /// Return true if the other box is a part of this one
    bool contains(const Box &def) const
    {
    	return (def.left >= left && def.top >= top && def.front >= front &&
			def.right <= right && def.bottom <= bottom && def.back <= back);
    }
    
    /// Get the width of this box
    size_t getWidth() const { return right-left; }
    /// Get the height of this box
    size_t getHeight() const { return bottom-top; }
    /// Get the depth of this box
    size_t getDepth() const { return back-front; }
};



template< typename T > struct TRect
{
    T left, top, right, bottom;

    TRect() {}

    TRect( T const & l, T const & t, T const & r, T const & b )
        : left( l ), top( t ), right( r ), bottom( b )
    {
    }

    TRect( TRect const & o )
        : left( o.left ), top( o.top ), right( o.right ), bottom( o.bottom )
    {
    }

    TRect & operator=( TRect const & o )
    {
        left = o.left;
        top = o.top;
        right = o.right;
        bottom = o.bottom;
        return *this;
    }

    T width() const
    {
        return right - left;
    }

    T height() const
    {
        return bottom - top;
    }
};

/** Structure used to define a rectangle in a 2-D floating point space.
*/
typedef TRect<float>            FloatRect;

/** Structure used to define a rectangle in a 2-D floating point space, 
	subject to double / single floating point settings.
*/
typedef TRect<u2real>           RealRect;

/** Structure used to define a rectangle in a 2-D integer space.
*/
typedef TRect<long>             Rect;



/** Defines the frame buffer types. */
enum FrameBufferType
{
    FBT_COLOUR  = 0x1,
    FBT_DEPTH   = 0x2,
    FBT_STENCIL = 0x4
};

/** Enumerates the wave types usable with the Ogre engine. */
enum WaveformType
{
    /// Standard sine wave which smoothly changes from low to high and back again.
    WFT_SINE,
    /// An angular wave with a constant increase / decrease speed with pointed peaks.
    WFT_TRIANGLE,
    /// Half of the time is spent at the min, half at the max with instant transition between.
    WFT_SQUARE,
    /// Gradual steady increase from min to max over the period with an instant return to min at the end.
    WFT_SAWTOOTH,
    /// Gradual steady decrease from max to min over the period, with an instant return to max at the end.
    WFT_INVERSE_SAWTOOTH,
    /// Pulse Width Modulation. Works like WFT_SQUARE, except the high to low transition is controlled by duty cycle. 
    /// With a duty cycle of 50% (0.5) will give the same output as WFT_SQUARE.
    WFT_PWM
};

/** Filtering options for textures / mipmaps. */
enum FilterOptions
{
    /// No filtering, used for FILT_MIP to turn off mipmapping
    FO_NONE,
    /// Use the closest pixel
    FO_POINT,
    /// Average of a 2x2 pixel area, denotes bilinear for MIN and MAG, trilinear for MIP
    FO_LINEAR,
    /// Similar to FO_LINEAR, but compensates for the angle of the texture plane
    FO_ANISOTROPIC
};

enum FilterType
{
    /// The filter used when shrinking a texture
    FT_MIN,
    /// The filter used when magnifying a texture
    FT_MAG,
    /// The filter used when determining the mipmap
    FT_MIP
};

/** High-level filtering options providing shortcuts to settings the
    minification, magnification and mip filters. */
enum TextureFilterOptions
{
    /// Equal to: min=FO_POINT, mag=FO_POINT, mip=FO_NONE
    TFO_NONE,
    /// Equal to: min=FO_LINEAR, mag=FO_LINEAR, mip=FO_POINT
    TFO_BILINEAR,
    /// Equal to: min=FO_LINEAR, mag=FO_LINEAR, mip=FO_LINEAR
    TFO_TRILINEAR,
    /// Equal to: min=FO_ANISOTROPIC, max=FO_ANISOTROPIC, mip=FO_LINEAR
	TFO_ANISOTROPIC
};

/** The polygon mode to use when rasterising. */
enum PolygonMode
{
    /// Only points are rendered.
    PM_POINTS           = 1,
    /// Wireframe models are rendered.
    PM_WIREFRAME        = 2,
    /// Solid polygons are rendered.
    PM_SOLID            = 3
};


/** Template class describing a simple pool of items.
*/
template <typename T>
class Pool
{
protected:
    typedef typename std::list<T> ItemList;
	ItemList mItems;
	U2_AUTO_MUTEX

public:
	Pool() {} 
	virtual ~Pool() {}

	/** Get the next item from the pool.
	@returns pair indicating whether there was a free item, and the item if so
	*/
	virtual std::pair<bool, T> removeItem()
	{
		U2_LOCK_AUTO_MUTEX
		std::pair<bool, T> ret;
		if (mItems.empty())
		{
			ret.first = false;
		}
		else
		{
			ret.first = true;
			ret.second = mItems.front();
			mItems.pop_front();
		}
		return ret;
	}

	/** Add a new item to the pool. 
	*/
	virtual void addItem(const T& i)
	{
		U2_LOCK_AUTO_MUTEX
		mItems.push_front(i);
	}
	/// Clear the pool
	virtual void clear()
	{
		U2_LOCK_AUTO_MUTEX
		mItems.clear();
	}
};


/// Alias / Texture name pair (first = alias, second = texture name)
typedef std::map<U2String, U2String>        AliasTextureNamePairList;


U2EG_NAMESPACE_END

#endif